/**
 * @file common.c
 * @author MaxwellWang
 * @brief 
 * @version v1.0.0
 * @date 2025/11/24
 * @copyright Copyright (c) 2025
 * this file is part of the mw-iap firmware
*/

#include "common.h"
#include "crc.h"
#include "packet.h"

static uint8_t IsConnectLoader= 0;  //是否连接上更新器


/**
 * @brief 从uart获取一个char值
 * @param key: The key is char
 * @retval 
*/
uint8_t GetCharFromUart(uint8_t *key){
    if(UART_GetFlagStatus(UartCH, UART_FLAG_RC) != RESET){
        *key = (uint8_t)UartCH->RDR;
        UART_ClearFlag(UartCH,UART_FLAG_RC);
        return 1;
    }else   
        return 0;
}
/**
 * @brief print char from uart
 * @param c
 * @retval None
 * 
*/
void PutCharFromUart(uint8_t c){
    UART_SendData_8bit(UartCH,c);
    while (UART_GetFlagStatus(CW_UART1, UART_FLAG_TXE) == RESET); 
}
/**
 * @brief Print a string on Terminal
 * @param s: The string to be printed
 * @retval None
*/
void PutStringFromUart(uint8_t *s){
    while(*s!='\0'){
        GetCharFromUart(s);
        s++;
    }
}
/**
 * @brief get update address & filelength &
 * 获取更新程序的配置 起始地址,程序总长度,加密方式?
 * 
*/
//void GetUpdate_Config(void){

//}
/**
 * @brief 开始发送起始升级信号
 * 
 * 
*/
void sendStartIAP(void){
    PutCharFromUart(STX);   // 发送启动升级信号
}
/**
 * @brief 扫描更新包数据 放在循环里一直扫描这个函数
 * 
 * 
*/
void ScanUpdatePack(void){
    uint8_t data[packMaxLen];
    int32_t data_len;
    if(Receive_Packet(data,&data_len,EnterUartScanByte)==0){    //一个字符的最长扫描时间
        //没有收到正确数据 发送重传命令
        if(IsConnectLoader)
        PutCharFromUart(NAK);   // 收到重传命令会重新传送上一帧数据
        else
        sendStartIAP();
        return;   //no right callback
    }
    //有收到正确信号
    IsConnectLoader = 1;
    //解码数据  data_len 真正数据的长度  擦除对应flash 和写入flash
    decodeCWRXpacket(data,data_len);
    //完成后发送一个ACK 再继续等待下一个信号
    PutCharFromUart(ACK);   //发送ACK 给主机告诉收到正确数据
}
/**
 * @brief pair to update of sender
 * 
 * 
*/
//void ConnectSenderCallback(void){
//    char *start = "start-cwiap";    //告诉主机自己是谁 可以准备升级了
//    uint8_t data[packMaxLen];
//    int32_t data_len;
//    PutStringFromUart(start);   //发送启动命令
//    //PutCharFromUart(SOH);   //标题开始
//    //等待收到接收应答信号
//    if(Receive_Packet(data,&data_len,EnterUartScanByte)==0){    //一个字符的最长扫描时间
//        //没有收到正确数据 发送重传命令
//        PutCharFromUart(NAK);   // 收到重传命令会重新传送上一帧数据
//        return 0;   //no right callback
//    }
//    //解码数据  data_len 真正数据的长度  擦除对应flash 和写入flash
//    decodeCWRXpacket(data,data_len);
//    //完成后发送一个ACK 再继续等待下一个信号
//    PutCharFromUart(ACK);   //发送ACK 给主机告诉收到正确数据
//}
/**
 * @brief send data
 * 
 * 
 * 
*/
void Send_Byte(uint8_t c){
    PutCharFromUart(c);
}
/**
 * @brief Receive byte from sender
 * @param c: char
 * @param timeOut: Timeout
 * @retval 0: fail
 *          1: ok
 * 
*/
uint8_t Receive_Byte(uint8_t *c,uint32_t timeOut){
    while(timeOut--){
        if(GetCharFromUart(c))
        return 1;
    }
    return 0;
}
/**
 * @brief Receice packet 按照固定格式收到数据了
 * st(bb)
 * @param data
 * @param len
 * @param timeOut
 * @retval 0: error return
 *          1: normally return
 * 
*/
int Receive_Packet(uint8_t *data,int32_t *len,uint32_t timeOut){
    uint8_t c;
    int32_t data_len;
    uint16_t crc_cale;
    //first byte is head 0xbb
    if(Receive_Byte(&c,timeOut)==0){
        return 0;
    }
    if(c!=0xbb)
        return 0;   //第一个数 必须是0xbb 否则错误
    //second byte is length byte num 1: 1byte <256 2:2byte <65536 3:3byte <0x1000000
    if(Receive_Byte(&c,timeOut)==0){
        return 0;
    }
    switch (c)
    {
        case 1:     //获取是一个byte /2byte /3byte 数据长度
            if(Receive_Byte(&c,timeOut)==0){
                return 0;
            }
            data_len = c;
            break;
        case 2:
            if(Receive_Byte(&c,timeOut)==0){
                return 0;
            }
            data_len = c;
            if(Receive_Byte(&c,timeOut)==0){
                return 0;
            }
            data_len |= (c<<8);
            break;
        case 3:
            if(Receive_Byte(&c,timeOut)==0){
                return 0;
            }
            data_len = c;
            if(Receive_Byte(&c,timeOut)==0){
                return 0;
            }
            data_len |= (c<<8);
            if(Receive_Byte(&c,timeOut)==0){
                return 0;
            }
            data_len |= (c<<16);
            break;
        default:
            //no config this length
            return 0;
    }
    for(int i=0;i<data_len;i++){
        if(Receive_Byte(data+i,timeOut)==0){
            return 0;
        }
    }
    if(Receive_Byte(&c,timeOut)==0){
        return 0;
    }
    crc_cale = c;
    if(Receive_Byte(&c,timeOut)==0){
        return 0;
    }
    crc_cale |= (c<<8);
    if(crc16(data,data_len)!=crc_cale)
        return 0;
    *len = data_len;        //解到正确数据
    return 1;
}
/**
 * @brief 进入bootloader 的解码条件
 * @param Non
 * @retval 0: no enter
 *          1: enter
*/
uint8_t IsEnterBootloader(void){
    uint8_t c;
    static int step = 0;
    char enterbuff[] = "mw-iap";
    if(Receive_Byte(&c,EnterUartScanByte)){    //一个字符的最长扫描时间
        //有数据
        if(c==enterbuff[step]){
            step++;
            if(enterbuff[step]=='\0'){
                //over
                return 1;
            }
        }else{
            step = 0;
        }
    }
    return 0;
}
